/**
 *   @file MCTreeNode.h
 */
#ifndef _MCTREENODE_H_
#define _MCTREENODE_H_

#include "../../common/BaseObject.h"

namespace cppflib
{

class DLHook;

namespace collections
{

namespace tree
{

class MultiChildTree;

/**
 *  A tree node for multi child tree
 *  
 *  @note the methods of this tree node are valid only when it is assigned to the root node of a 
 *        multi child tree or the child of another node
 */
class _DLLAPI MCTreeNode : public BaseObject
{
private:
    MultiChildTree * pMCTree;
    BaseObject * pKey;
    MCTreeNode * pParent;
    BaseObject * pChildList; ///< a LinkedHashtable if uniqueChildKeyOnly is true, otherwise, a ListCppObj
    cppflib::DLHook *pListHook; ///< pointer to the hook of parent's child list, for use in GetNextSibling and GetPrevSibling

    void ClearAttachingTree();
    void SetAttachingTree(MultiChildTree *pMCTree);
    void ClearParentAndTree();
    
protected:
    MCTreeNode(void);
        
public:
    explicit MCTreeNode(BaseObject *pKey);
    virtual ~MCTreeNode(void);

    virtual MCTreeNode * GetParent();
    virtual MCTreeNode * GetNextSibling();
    virtual MCTreeNode * GetPrevSibling();
    virtual MCTreeNode * GetChild(u32_t index);
    virtual MCTreeNode * GetChild(const BaseObject &key);
    virtual MultiChildTree * GetAttachedTree();
    virtual const BaseObject * GetKey();
    virtual u32_t GetDirectChildCount();
    virtual u32_t GetAllChildCount();
    virtual bool HasNoParent();
    virtual bool IsRootNode();
    virtual u32_t GetDepth();

    virtual bool AddChild(MCTreeNode * pChild);
    virtual bool DeleteChild(u32_t index);
    virtual bool DeleteChild(const BaseObject &key);
    virtual void DeleteAllChildren();
    virtual bool IsAncestor(MCTreeNode *pNode);
    virtual bool Move(MCTreeNode *pNode);
    virtual void DetachFromTree();

    friend class MultiChildTree;
};

}  // end of namespace tree

}  // end of namespace collections

}  // end of namespace cppflib


#endif
